import { ConfigUtils } from "@dendronhq/common-all";
import { AssertUtils, NoteTestUtilsV4 } from "@dendronhq/common-test-utils";
import { ENGINE_HOOKS, TestConfigUtils } from "@dendronhq/engine-test-utils";
import { describe } from "mocha";
import * as vscode from "vscode";
import { InsertNoteIndexCommand } from "../../commands/InsertNoteIndexCommand";
import { ExtensionProvider } from "../../ExtensionProvider";
import { VSCodeUtils } from "../../vsCodeUtils";
import { WSUtils } from "../../WSUtils";
import { expect } from "../testUtilsv2";
import {
  describeMultiWS,
  runLegacyMultiWorkspaceTest,
  setupBeforeAfter,
} from "../testUtilsV3";

suite("InsertNoteIndex", function () {
  const ctx: vscode.ExtensionContext = setupBeforeAfter(this);

  describe("basic", () => {
    test("basic", (done) => {
      runLegacyMultiWorkspaceTest({
        ctx,
        preSetupHook: async ({ wsRoot, vaults }) => {
          await ENGINE_HOOKS.setupBasic({ wsRoot, vaults });
        },
        onInit: async ({ engine }) => {
          const foo = (await engine.getNoteMeta("foo")).data!;
          const cmd = new InsertNoteIndexCommand(
            ExtensionProvider.getExtension()
          );

          await WSUtils.openNote(foo);
          const editor = VSCodeUtils.getActiveTextEditorOrThrow();
          editor.selection = new vscode.Selection(9, 0, 9, 0);
          await cmd.execute({});
          const body = editor.document.getText();
          expect(
            await AssertUtils.assertInString({
              body,
              match: [["## Index", "- [[Ch1|foo.ch1]]"].join("\n")],
            })
          );
          done();
        },
      });
    });

    test("basic with markers", (done) => {
      runLegacyMultiWorkspaceTest({
        ctx,
        preSetupHook: async ({ wsRoot, vaults }) => {
          await ENGINE_HOOKS.setupBasic({ wsRoot, vaults });
        },
        onInit: async ({ engine }) => {
          const foo = (await engine.getNoteMeta("foo")).data!;
          const cmd = new InsertNoteIndexCommand(
            ExtensionProvider.getExtension()
          );

          await WSUtils.openNote(foo);
          const editor = VSCodeUtils.getActiveTextEditorOrThrow();
          editor.selection = new vscode.Selection(9, 0, 9, 0);
          await cmd.execute({ marker: true });
          const body = editor.document.getText();
          expect(
            await AssertUtils.assertInString({
              body,
              match: [
                [
                  "<!-- Autogenerated Index Start -->",
                  "## Index",
                  "- [[Ch1|foo.ch1]]",
                  "<!-- Autogenerated Index End -->",
                ].join("\n"),
              ],
            })
          );
          done();
        },
      });
    });
  });

  describe("non-basic cases", () => {
    test("noXVaultWikiLink: false", (done) => {
      runLegacyMultiWorkspaceTest({
        ctx,
        preSetupHook: async ({ wsRoot, vaults }) => {
          await ENGINE_HOOKS.setupBasic({ wsRoot, vaults });
        },
        onInit: async ({ wsRoot, engine }) => {
          TestConfigUtils.withConfig(
            (config) => {
              ConfigUtils.setWorkspaceProp(
                config,
                "enableXVaultWikiLink",
                true
              );
              return config;
            },
            { wsRoot }
          );

          const foo = (await engine.getNoteMeta("foo")).data!;
          const cmd = new InsertNoteIndexCommand(
            ExtensionProvider.getExtension()
          );

          await WSUtils.openNote(foo);
          const editor = VSCodeUtils.getActiveTextEditorOrThrow();
          editor.selection = new vscode.Selection(9, 0, 9, 0);
          await cmd.execute({});
          const body = editor.document.getText();
          expect(
            await AssertUtils.assertInString({
              body,
              match: [
                ["## Index", "- [[Ch1|dendron://vault1/foo.ch1]]"].join("\n"),
              ],
            })
          );
          done();
        },
      });
    });

    test("insertNoteIndex.marker: true", (done) => {
      runLegacyMultiWorkspaceTest({
        ctx,
        preSetupHook: async ({ wsRoot, vaults }) => {
          await ENGINE_HOOKS.setupBasic({ wsRoot, vaults });
        },
        onInit: async ({ wsRoot, engine }) => {
          TestConfigUtils.withConfig(
            (config) => {
              ConfigUtils.setCommandsProp(config, "insertNoteIndex", {
                enableMarker: true,
              });
              return config;
            },
            { wsRoot }
          );

          const foo = (await engine.getNoteMeta("foo")).data!;
          const cmd = new InsertNoteIndexCommand(
            ExtensionProvider.getExtension()
          );

          await WSUtils.openNote(foo);
          const editor = VSCodeUtils.getActiveTextEditorOrThrow();
          editor.selection = new vscode.Selection(9, 0, 9, 0);
          await cmd.execute({});
          const body = editor.document.getText();
          expect(
            await AssertUtils.assertInString({
              body,
              match: [
                [
                  "<!-- Autogenerated Index Start -->",
                  "## Index",
                  "- [[Ch1|foo.ch1]]",
                  "<!-- Autogenerated Index End -->",
                ].join("\n"),
              ],
            })
          );
          done();
        },
      });
    });
  });

  describeMultiWS(
    "GIVEN foo tag without parent note tags",
    {
      preSetupHook: async ({ wsRoot, vaults }) => {
        await NoteTestUtilsV4.createNote({
          vault: vaults[0],
          wsRoot,
          fname: "root",
          body: "this is root",
        });
        await NoteTestUtilsV4.createNote({
          vault: vaults[0],
          wsRoot,
          fname: "tags.foo",
          body: "this is tag foo",
        });
      },
    },
    () => {
      test("THEN insert note index add tags as index", async () => {
        const engine = ExtensionProvider.getEngine();
        const rootNote = (await engine.getNoteMeta("root")).data!;
        await ExtensionProvider.getWSUtils().openNote(rootNote);
        const editor = VSCodeUtils.getActiveTextEditorOrThrow();
        const cmd = new InsertNoteIndexCommand(
          ExtensionProvider.getExtension()
        );
        editor.selection = new vscode.Selection(9, 0, 9, 0);
        await cmd.execute({});
        const body = editor.document.getText();
        expect(
          await AssertUtils.assertInString({
            body,
            match: [["## Index", "- [[Tags|tags]]"].join("\n")],
          })
        );
      });
    }
  );

  describeMultiWS(
    "GIVEN foo tag with parent note tags",
    {
      preSetupHook: async ({ wsRoot, vaults }) => {
        await NoteTestUtilsV4.createNote({
          vault: vaults[0],
          wsRoot,
          fname: "root",
          body: "this is root",
        });
        await NoteTestUtilsV4.createNote({
          vault: vaults[0],
          wsRoot,
          fname: "tags",
          body: "this is tag",
        });
        await NoteTestUtilsV4.createNote({
          vault: vaults[0],
          wsRoot,
          fname: "tags.foo",
          body: "this is tag foo",
        });
      },
    },
    () => {
      test("THEN insert note index add tags as index", async () => {
        const engine = ExtensionProvider.getEngine();
        const rootNote = (await engine.getNoteMeta("root")).data!;
        await ExtensionProvider.getWSUtils().openNote(rootNote);
        const editor = VSCodeUtils.getActiveTextEditorOrThrow();
        const cmd = new InsertNoteIndexCommand(
          ExtensionProvider.getExtension()
        );
        editor.selection = new vscode.Selection(9, 0, 9, 0);
        await cmd.execute({});
        const body = editor.document.getText();
        expect(
          await AssertUtils.assertInString({
            body,
            match: [["## Index", "- [[Tags|tags]]"].join("\n")],
          })
        );
      });
    }
  );
});
